class Gun:
    """定义一个枪类"""

    def __init__(self, name: str, bullet: int = 0, max_num: int = 30):
        # 枪名/枪类型名称
        self.name = name
        # 初始状态子弹数量
        self.bullet = bullet
        # 此枪最大可装填的子弹数
        self.max_num = max_num

    def fire_bullet(self):
        """发射子弹"""
        # 如果枪里有子弹，连发3颗子弹
        if self.bullet > 0:
            print('biu~biu~biu~')
            self.bullet -= 3
        else:
            # 否则枪里没有子弹，打印无法射击
            print('没有子弹，无法射击')

    def add_bullet(self, bullet_num: int):
        # 如果枪里剩余子弹和待装填子弹不超过最大可装填数目，增量 = 用户输入的装填子弹数
        if self.bullet + bullet_num <= self.max_num:
            increase = bullet_num
        else:
            # 否则增量 = 最大可装填数目 - 枪里剩余子弹
            increase = self.max_num - self.bullet

        # 实际装填子弹数 = 枪里剩余子弹 + 增量
        self.bullet += increase
        print(f'{self.name}已装填{increase}发子弹(最多可装填{self.max_num}发子弹)')

    def __str__(self):
        return f'{self.name}有{self.bullet}发子弹'


class Solider:
    """定义一个士兵类"""

    def __init__(self, name: str, gun: Gun = None):
        if not isinstance(gun, Gun):
            raise TypeError(f'{gun} is not type of <class Gun>')

        # 士兵的名字
        self.name = name
        # 士兵的枪支
        self.gun = gun

    def shot(self):
        """士兵扣动扳机开火"""
        # 如果没有枪，打印没有枪无法开火
        if not self.gun:
            print('没有枪无法开火')
            return

        # 否则有枪，则调用枪的发射子弹fire_bullet方法进行开火
        self.gun.fire_bullet()

    def reload(self, bullet_num: int):
        """装填子弹"""
        if bullet_num <= 0:
            print('装填子弹数必须大于零')
            return

        if not self.gun:
            print('没有枪无法装填子弹')
            return

        self.gun.add_bullet(bullet_num)

    def __str__(self):
        # 如果没有枪
        if not self.gun:
            return f'士兵{self.name}没有枪'

        # 否则有枪，打印士兵xxx有一把xxx枪，xxx枪有xxx发子弹
        return f'士兵{self.name}的{self.gun}'


if __name__ == '__main__':
    AK47 = Gun('AK47')
    print(AK47)

    Ryan = Solider('Ryan', AK47)
    print(Ryan)
    Ryan.shot()

    Ryan.reload(40)
    print(Ryan)

    Ryan.shot()
    print(Ryan)
